昨天有个同学跟我说约瑟夫环问题的O(n)解法很费解,看不懂,所以我就看了一下,发现这种解法真是太奇妙了,所以打算写一下。
约瑟夫环问题(Josephus)问题描述:
输入m和n,有n个人编号从0到n-1,这n个人开始从0到m-1顺序循环数数,每次数到m-1的人就出列,剩下的人继续,直至剩余最后一人,求最后剩余的那个人的编号。
我觉得总体上来讲O(n)算法应该是分治的思想,首先是Divide,将n个人的游戏变成n-1个人,然后再变成n-2个人,......,直到最后剩余1个人。然后是Conquer,如果我们知道n-1个人的游戏结果的话,怎么得到n个人游戏的结果呢?我们来看看从n个人变成n-1个人后的情况,当m>n时,需要把下面的m变成m%n,为了简便我就直接写m了。
•
0,1,2,3,4,…,m-2,
m-1,m,…,n-1
// 原始n个人的编号,第一轮报数后,m-1将被删除
•m,…,n-1,
0,1,2,3,4,…,m-2// 把前m-1人挪到编号n-1后,即剩余n-1个人的原始编号{x}
•0,…,n-m-1,
n-m,…,n-2// 剩余n-1个人重新编号{y}